/**
 * Copyright (c) 2009 Teoti Graphix, LLC See:
 *     http://tkarchitecture.teotigraphix.org
 * 
 * Permission is hereby granted, free of charge, to any person
 * obtaining a copy of this software and associated documentation
 * files (the "Software"), to deal in the Software without
 * restriction, including without limitation the rights to use,
 * copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the
 * Software is furnished to do so, subject to the following
 * conditions:
 * 
 * The above copyright notice and this permission notice shall be
 * included in all copies or substantial portions of the Software.
 * 
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
 * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
 * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
 * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
 * OTHER DEALINGS IN THE SOFTWARE.
 * 
 * @author Michael Schmalle mschmalle@teotigraphix.com
 */
package org.example.ui.model
{

import flash.events.Event;

import org.example.ui.component.Button;
import org.example.ui.component.button.ButtonState;
import org.teotigraphix.dx.interfaces.ISkinAware;
import org.teotigraphix.dx.patterns.model.ComponentModelCore;

/**
 * The core behavioral service abstracted from the <code>Button</code> 
 * component.
 * 
 * <p><strong>Component State;</strong></p>
 * <ul>
 * <li>Maintains the <code>IButton</code> interface model.</li>
 * <li>Lists service model update interests; <code>listValueInterests()</code>.</li>
 * </ul>
 * 
 * <p><strong>Skin State;</strong></p>
 * <ul>
 * <li>Maintains the current skin state; <code>getSkinState()</code>.</li>
 * <li>Invalidates the current skin state; <code>invalidateButtonState()</code>.</li>
 * </ul>
 * 
 * <p><strong>Behavioral State;</strong></p>
 * <ul>
 * <li>Maintains the <code>IButtonModel</code> interface model.</li>
 * <li>Maintains the hovered over state; <code>hoveredOver</code>.</li>
 * <li>Maintains the key pressed state; <code>keyboardPressed</code>.</li>
 * <li>Maintains the mouse captured state; <code>mouseCaptured</code>.</li>
 * <li>Maintains the mouse down state; <code>isDown()</code>.</li>
 * </ul>
 * 
 * @copyright Teoti Graphix, LLC
 * @author Michael Schmalle
 * @date 12-08-08
 */
public class ButtonModelCore 
	   extends ComponentModelCore
	   implements IButtonModel
{
	//--------------------------------------------------------------------------
	//
	//  IButton API :: Properties
	//
	//--------------------------------------------------------------------------
	
	[Bindable]
	
	/**
	 * @copy org.example.model.IButtonModel#content
	 */
	public var content:*;
	
	[Bindable]
	
	/**
	 * @copy org.example.model.IButtonModel#label
	 */	
	public var label:String;
	
	[Bindable]
	
	/**
	 * @copy org.example.model.IButtonModel#icon
	 */	
	public var icon:Class;
	
	//--------------------------------------------------------------------------
	//
	//  IButtonModel API :: Properties
	//
	//--------------------------------------------------------------------------
	
	//----------------------------------
	//  hoveredOver
	//----------------------------------
	
	/**
	 * @private
	 */
	private var _hoveredOver:Boolean;
	
	/**
	 * @copy org.example.model.IButtonModel#hoveredOver
	 */
	public function get hoveredOver():Boolean
	{
		return _hoveredOver;
	}
	
	/**
	 * @private
	 */
	public function set hoveredOver(value:Boolean):void
	{
		if (_hoveredOver == value)
			return;
				
		_hoveredOver = value;
		
		invalidateButtonState();
	}

	//----------------------------------
	//  keyboardPressed
	//----------------------------------
	
	/**
	 * @private
	 */	
	private var _keyboardPressed:Boolean = false; 
	
	/**
	 * @copy org.example.model.IButtonModel#keyboardPressed
	 */
	public function get keyboardPressed():Boolean
	{
		return _keyboardPressed;
	}
	
	/**
	 * @private
	 */
	public function set keyboardPressed(value:Boolean):void
	{
		if (value == _keyboardPressed)
			return;
		
		_keyboardPressed = value;
		
		invalidateButtonState();
	}
	
	//----------------------------------
	//  mouseCaptured
	//----------------------------------
	
	/**
	 * @private
	 */
	private var _mouseCaptured:Boolean;
	
	/**
	 * @copy org.example.model.IButtonModel#mouseCaptured
	 */
	public function get mouseCaptured():Boolean
	{
		return _mouseCaptured;
	}
	
	/**
	 * @private
	 */
	public function set mouseCaptured(value:Boolean):void
	{
		if (_mouseCaptured == value)
			return;

		_mouseCaptured = value;
		
		invalidateButtonState();
		dispatchEvent(new Event("mouseCapturedChange"));		
	}
	
	//--------------------------------------------------------------------------
	//
	//  Protected :: Properties
	//
	//--------------------------------------------------------------------------
	
	//----------------------------------
	//  button
	//----------------------------------
	
	/**
	 * @private
	 */
	protected function get button():Button
	{
		return component as Button;
	}	
	
	//--------------------------------------------------------------------------
	//
	//  Constructor
	//
	//--------------------------------------------------------------------------
	
	/**
	 * Constructor.
	 */
	public function ButtonModelCore()
	{
		super();
	}
	
	//--------------------------------------------------------------------------
	//
	//  Overridden Public :: Methods
	//
	//--------------------------------------------------------------------------
	
	/**
	 * @inheritDoc
	 */
	override public function listValueInterests():Array
	{
		return ["content", "icon"];
	}
	
	/**
	 * @inheritDoc
	 */
	override public function getSkinState():String
	{
		if (!button.enabled)
			return ButtonState.DISABLED;
		
		if (isDown())
			return ButtonState.DOWN;
		
		if (hoveredOver || mouseCaptured)
			return ButtonState.OVER;
			
		return ButtonState.UP;
	}
	
	//--------------------------------------------------------------------------
	//
	//  IButtonModel API :: Methods
	//
	//--------------------------------------------------------------------------
	
	/**
	 * Button is down when either the keyboard is pressed or the mouse is captured
	 * and the button is hovered over.
	 * 
	 * @copy org.example.model.IButtonModel#isDown()
	 */
	public function isDown():Boolean
	{
		if (!button.enabled)
			return false;
		
		if (keyboardPressed)
			return true;
		
		if (mouseCaptured && (hoveredOver/* || stickyHighlighting*/))
			return true;
		
		return false;
	}	
	
	//--------------------------------------------------------------------------
	//
	//  Overridden Protected :: Methods
	//
	//--------------------------------------------------------------------------
	
	override protected function commitComponent():void
	{
		super.commitComponent();
		
		if (button)
		{
			button.mouseChildren = false;
		}
	}
	
	/**
	 * Invlaidated the Component's skin state.
	 */
	protected function invalidateButtonState():void
	{
		ISkinAware(component).invalidateSkin(); 
	}	
}
}